package com.mc.fastkit.ext

import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableString
import android.text.TextPaint
import android.text.style.BackgroundColorSpan
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StrikethroughSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import android.view.View
import androidx.annotation.DrawableRes
import androidx.core.graphics.toColorInt
import com.mc.fastkit.span.ExactlySizePan
import com.mc.fastkit.span.ExtendImageSpan
import com.mc.fastkit.span.TextGradientSpan
import com.mc.fastkit.span.TypefaceSpan

/**
 * 修改指定[range]文字的文字大小
 * @param range 文字范围
 * @param textSize 具体需要修改的值
 */
fun CharSequence.toSizeSpan(range: IntRange, textSize: Float): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            ExactlySizePan(textSize), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toSizeSpan(textSize: Float): CharSequence {
    return toSizeSpan(0..length, textSize)
}

/**
 * 修改指定[range]文字的文字前景色
 * @param range 文字范围
 * @param color 要改变的颜色
 */
fun CharSequence.toColorSpan(range: IntRange, color: Int): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            ForegroundColorSpan(color), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toColorSpan(color: Int): CharSequence {
    return toColorSpan(0..length, color)
}

fun CharSequence.toColorSpan(color: String): CharSequence {
    return toColorSpan(0..length, color.toColorInt())
}

/**
 * 修改指定[range]文字的文字背景色
 * @param range 文字范围
 * @param color 要改变的颜色
 */
fun CharSequence.toBackgroundColorSpan(range: IntRange, color: Int): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            BackgroundColorSpan(color), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toBackgroundColorSpan(color: Int): CharSequence {
    return toBackgroundColorSpan(0..length, color)
}

/**
 * 为指定[range]的文字添加删除线
 * @param range 文字范围
 */
fun CharSequence.toStrikethroughSpan(range: IntRange): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            StrikethroughSpan(), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toStrikethroughSpan(): CharSequence {
    return toStrikethroughSpan(0..length)
}

/**
 * 为指定[range]的文字添加下划线
 * @receiver CharSequence
 * @param range IntRange
 * @return CharSequence
 */
fun CharSequence.toUnderlineSpan(range: IntRange): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            UnderlineSpan(), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toUnderlineSpan(): CharSequence {
    return toUnderlineSpan(0..length)
}

/**
 * 为指定[range]的文字添加点击事件
 * @param range 文字范围
 * @param textColor 文字颜色
 * @param clickListener 点击事件
 * @return CharSequence
 */
fun CharSequence.toClickSpan(
    range: IntRange,
    textColor: Int = 0,
    clickListener: ((View) -> Unit)?
): CharSequence {
    return SpannableString(this).apply {
        val clickableSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                clickListener?.invoke(widget)
            }

            override fun updateDrawState(textPaint: TextPaint) {
                if (textColor != 0) {
                    textPaint.color = textColor
                }
            }
        }
        setSpan(clickableSpan, range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    }
}

fun CharSequence.toClickSpan(textColor: Int = 0, clickListener: ((View) -> Unit)?): CharSequence {
    return toClickSpan(0..length, textColor, clickListener)
}

/**
 * 为指定[range]的文字添加Style效果
 * @param range 文字范围
 * @param style 例如[Typeface.BOLD]
 */
fun CharSequence.toStyleSpan(range: IntRange, style: Int): CharSequence {
    return SpannableString(this).apply {
        setSpan(StyleSpan(style), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    }
}

fun CharSequence.toStyleSpan(style: Int): CharSequence {
    return toStyleSpan(0..length, style)
}

/**
 * 为指定[range]的文字设置字体
 * @param range 文字范围
 * @param typeface 自定义字体
 */
fun CharSequence.toTypeFaceSpan(range: IntRange, typeface: Typeface): CharSequence {
    return SpannableString(this).apply {
        setSpan(TypefaceSpan(typeface), range.first, range.last, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    }
}

fun CharSequence.toTypeFaceSpan(typeface: Typeface): CharSequence {
    return toTypeFaceSpan(0..length, typeface)
}

/**
 * 为指定[range]的文字设置图片
 * @param range 文字范围
 * @param imageRes 图片
 * @param verticalAlignment 垂直对齐方式
 * @param leftMargin Int
 * @param rightMargin Int
 * @param imageWidth Int
 * @param imageHeight Int
 * @return CharSequence
 */
fun CharSequence.toImageSpan(
    range: IntRange,
    @DrawableRes imageRes: Int,
    verticalAlignment: Int = ExtendImageSpan.ALIGN_CENTER,
    leftMargin: Int = 0,
    rightMargin: Int = 0,
    imageWidth: Int = -1,
    imageHeight: Int = -1
): CharSequence {
    return toImageSpan(
        range, app.getDrawableStrict(imageRes)!!, verticalAlignment, leftMargin, rightMargin,
        imageWidth,
        imageHeight
    )
}

/**
 * 为指定[range]的文字设置图片
 * @param range 文字范围
 * @param drawable 图片
 * @param verticalAlignment 垂直对齐方式
 * @param leftMargin Int
 * @param rightMargin Int
 * @param imageWidth Int
 * @param imageHeight Int
 * @return CharSequence
 */
fun CharSequence.toImageSpan(
    range: IntRange,
    drawable: Drawable,
    verticalAlignment: Int = ExtendImageSpan.ALIGN_CENTER,
    leftMargin: Int = 0,
    rightMargin: Int = 0,
    imageWidth: Int = -1,
    imageHeight: Int = -1
): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            ExtendImageSpan(
                drawable.apply {
                    val width = if (imageWidth == -1) intrinsicWidth else imageWidth
                    val height = if (imageHeight == -1) intrinsicHeight else imageHeight
                    setBounds(0, 0, width, height)
                },
                verticalAlignment,
                leftMargin,
                rightMargin
            ),
            range.first,
            range.last,
            Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toGradientSpan(
    range: IntRange,
    colors: IntArray,
    position: FloatArray? = null,
    isVertical: Boolean = false
): CharSequence {
    return SpannableString(this).apply {
        setSpan(
            TextGradientSpan(this, colors, position, isVertical), range.first, range.last,
            Spannable.SPAN_INCLUSIVE_INCLUSIVE
        )
    }
}

fun CharSequence.toGradientSpan(
    colors: IntArray,
    position: FloatArray? = null,
    isVertical: Boolean = false
): CharSequence {
    return toGradientSpan(0..length, colors, position, isVertical)
}